import { Viewport, Column } from '../types'

export interface ScrollPosition {
  scrollTop: number
  scrollLeft: number
}

export interface ScrollbarInfo {
  vertical: {
    visible: boolean
    position: number
    size: number
    thumbSize: number
  }
  horizontal: {
    visible: boolean
    position: number
    size: number
    thumbSize: number
  }
}

export class VirtualScrollManager {
  private containerWidth: number = 0
  private containerHeight: number = 0
  private contentWidth: number = 0
  private contentHeight: number = 0
  
  private scrollTop: number = 0
  private scrollLeft: number = 0
  private maxScrollTop: number = 0
  private maxScrollLeft: number = 0
  
  private rowHeight: number = 30
  private headerHeight: number = 35
  private rowCount: number = 0
  private columns: Column[] = []
  
  private scrollbarWidth: number = 10
  private minScrollbarThumbSize: number = 20
  
  // 缓冲区大小（渲染视口外的行数）
  private bufferSize: number = 5
  
  // 动态行高支持
  private rowHeights: Map<number, number> = new Map()
  private defaultRowHeight: number = 30
  
  // 行号列相关
  private showRowNumber: boolean = true
  private rowNumberWidth: number = 50
  
  // 滚动平滑度设置
  private smoothScrolling: boolean = true
  private scrollSensitivity: number = 1

  constructor(options: {
    containerWidth: number
    containerHeight: number
    rowHeight: number
    headerHeight: number
    scrollbarWidth?: number
  }) {
    this.containerWidth = options.containerWidth
    this.containerHeight = options.containerHeight
    this.rowHeight = options.rowHeight
    this.defaultRowHeight = options.rowHeight
    this.headerHeight = options.headerHeight
    this.scrollbarWidth = options.scrollbarWidth || 10
  }

  // 设置数据信息
  setDataInfo(rowCount: number, columns: Column[]): void {
    this.rowCount = rowCount
    this.columns = columns
    this.calculateContentSize()
    this.calculateMaxScroll()
  }

  // 设置容器大小
  setContainerSize(width: number, height: number): void {
    this.containerWidth = width
    this.containerHeight = height
    this.calculateMaxScroll()
  }

  // 设置滚动位置
  setScrollPosition(scrollTop: number, scrollLeft: number): void {
    this.scrollTop = Math.max(0, Math.min(scrollTop, this.maxScrollTop))
    this.scrollLeft = Math.max(0, Math.min(scrollLeft, this.maxScrollLeft))
  }

  // 滚动到指定行
  scrollToRow(row: number): void {
    let targetTop = 0
    
    // 累加之前所有行的高度
    for (let i = 0; i < row && i < this.rowCount; i++) {
      targetTop += this.getRowHeight(i)
    }
    
    this.setScrollPosition(targetTop, this.scrollLeft)
  }

  // 滚动到指定列
  scrollToColumn(col: number): void {
    let targetLeft = 0
    for (let i = 0; i < col && i < this.columns.length; i++) {
      targetLeft += this.columns[i].width || 100
    }
    this.setScrollPosition(this.scrollTop, targetLeft)
  }

  // 滚动到指定单元格
  scrollToCell(row: number, col: number): void {
    this.scrollToRow(row)
    this.scrollToColumn(col)
  }

  // 处理鼠标滚轮
  handleWheel(deltaX: number, deltaY: number): boolean {
    const oldTop = this.scrollTop
    const oldLeft = this.scrollLeft
    
    // 根据 delta 的绝对值判断滚动类型
    // 小数值通常来自触控板，大数值来自鼠标滚轮
    const isTouchpad = Math.abs(deltaY) < 10 || Math.abs(deltaX) < 10
    
    let scrollSpeed: number
    if (isTouchpad) {
      // 触控板：使用原始值，提供细腻的滚动体验
      scrollSpeed = 1
    } else {
      // 鼠标滚轮：每次滚动2行的高度
      scrollSpeed = this.rowHeight * 2 / 100
    }
    
    // 应用滚动灵敏度
    scrollSpeed *= this.scrollSensitivity
    
    // 计算新的滚动位置
    const newScrollTop = this.scrollTop + deltaY * scrollSpeed
    const newScrollLeft = this.scrollLeft + deltaX * scrollSpeed
    
    this.setScrollPosition(newScrollTop, newScrollLeft)
    
    return oldTop !== this.scrollTop || oldLeft !== this.scrollLeft
  }

  // 获取当前视口
  getViewport(): Viewport {
    const visibleHeight = this.containerHeight - this.headerHeight
    
    // 找到起始行（考虑动态行高）
    let startRow = 0
    let currentY = -this.scrollTop
    
    for (let i = 0; i < this.rowCount; i++) {
      const rowHeight = this.getRowHeight(i)
      if (currentY + rowHeight > 0) {
        startRow = Math.max(0, i - this.bufferSize)
        break
      }
      currentY += rowHeight
    }
    
    // 找到结束行（考虑动态行高）
    let endRow = this.rowCount - 1  // 默认为最后一行
    currentY = this.getRowY(startRow) - this.headerHeight
    
    for (let i = startRow; i < this.rowCount; i++) {
      currentY += this.getRowHeight(i)
      if (currentY > visibleHeight) {
        endRow = Math.min(this.rowCount - 1, i + this.bufferSize)
        break
      }
    }
    
    // 确保至少显示一定数量的行（但不超过实际行数）
    const minVisibleRows = 20
    if (endRow - startRow < minVisibleRows) {
      endRow = Math.min(this.rowCount - 1, startRow + minVisibleRows)
    }
    
    // 计算可见列
    let startCol = 0
    let endCol = this.columns.length - 1
    let accWidth = 0
    let leftOffset = 0
    
    // 找到起始列
    for (let i = 0; i < this.columns.length; i++) {
      const colWidth = this.columns[i].width || 100
      if (accWidth + colWidth > this.scrollLeft) {
        startCol = Math.max(0, i - 1) // 包含部分可见的前一列
        leftOffset = accWidth
        break
      }
      accWidth += colWidth
    }
    
    // 找到结束列
    accWidth = leftOffset
    for (let i = startCol; i < this.columns.length; i++) {
      const colWidth = this.columns[i].width || 100
      accWidth += colWidth
      if (accWidth > this.scrollLeft + this.containerWidth) {
        endCol = Math.min(this.columns.length - 1, i + 1) // 包含部分可见的后一列
        break
      }
    }
    
    return {
      startRow,
      endRow,
      startCol,
      endCol,
      scrollTop: this.scrollTop,
      scrollLeft: this.scrollLeft
    }
  }

  // 获取滚动条信息
  getScrollbarInfo(): ScrollbarInfo {
    const hasVerticalScrollbar = this.contentHeight > this.containerHeight
    const hasHorizontalScrollbar = this.contentWidth > this.containerWidth
    
    // 垂直滚动条
    const verticalThumbSize = Math.max(
      this.minScrollbarThumbSize,
      (this.containerHeight / this.contentHeight) * this.containerHeight
    )
    const verticalMaxPosition = this.containerHeight - verticalThumbSize
    const verticalPosition = (this.scrollTop / this.maxScrollTop) * verticalMaxPosition
    
    // 水平滚动条
    const horizontalThumbSize = Math.max(
      this.minScrollbarThumbSize,
      (this.containerWidth / this.contentWidth) * this.containerWidth
    )
    const horizontalMaxPosition = this.containerWidth - horizontalThumbSize
    const horizontalPosition = (this.scrollLeft / this.maxScrollLeft) * horizontalMaxPosition
    
    return {
      vertical: {
        visible: hasVerticalScrollbar,
        position: isNaN(verticalPosition) ? 0 : verticalPosition,
        size: this.containerHeight,
        thumbSize: verticalThumbSize
      },
      horizontal: {
        visible: hasHorizontalScrollbar,
        position: isNaN(horizontalPosition) ? 0 : horizontalPosition,
        size: this.containerWidth,
        thumbSize: horizontalThumbSize
      }
    }
  }

  // 处理滚动条拖动
  handleScrollbarDrag(vertical: boolean, position: number): void {
    if (vertical) {
      const scrollbarInfo = this.getScrollbarInfo()
      const maxPosition = this.containerHeight - scrollbarInfo.vertical.thumbSize
      const ratio = position / maxPosition
      this.setScrollPosition(ratio * this.maxScrollTop, this.scrollLeft)
    } else {
      const scrollbarInfo = this.getScrollbarInfo()
      const maxPosition = this.containerWidth - scrollbarInfo.horizontal.thumbSize
      const ratio = position / maxPosition
      this.setScrollPosition(this.scrollTop, ratio * this.maxScrollLeft)
    }
  }

  // 获取行的Y坐标
  getRowY(row: number): number {
    let y = this.headerHeight - this.scrollTop
    
    // 累加之前所有行的高度
    for (let i = 0; i < row; i++) {
      y += this.getRowHeight(i)
    }
    
    return y
  }

  // 获取列的X坐标
  getColumnX(col: number): number {
    let x = 0
    for (let i = 0; i < col && i < this.columns.length; i++) {
      x += this.columns[i].width || 100
    }
    return x - this.scrollLeft
  }

  // 根据坐标获取行索引
  getRowByY(y: number): number {
    if (y < this.headerHeight) {
      return -1 // 表头
    }
    
    let currentY = this.headerHeight - this.scrollTop
    
    for (let row = 0; row < this.rowCount; row++) {
      const rowHeight = this.getRowHeight(row)
      if (y >= currentY && y < currentY + rowHeight) {
        return row
      }
      currentY += rowHeight
      
      // 如果已经超过了Y位置，就不用继续检查了
      if (currentY > y) {
        break
      }
    }
    
    return -1
  }

  // 根据坐标获取列索引
  getColumnByX(x: number): number {
    const targetX = x + this.scrollLeft
    let accWidth = 0
    
    for (let i = 0; i < this.columns.length; i++) {
      const colWidth = this.columns[i].width || 100
      if (targetX >= accWidth && targetX < accWidth + colWidth) {
        return i
      }
      accWidth += colWidth
    }
    
    return -1
  }

  // 获取当前滚动位置
  getScrollPosition(): ScrollPosition {
    return {
      scrollTop: this.scrollTop,
      scrollLeft: this.scrollLeft
    }
  }

  // 获取内容尺寸
  getContentSize(): { width: number; height: number } {
    return {
      width: this.contentWidth,
      height: this.contentHeight
    }
  }

  // 获取容器尺寸
  getContainerSize(): { width: number; height: number } {
    return {
      width: this.containerWidth,
      height: this.containerHeight
    }
  }

  // 是否需要垂直滚动条
  needsVerticalScrollbar(): boolean {
    return this.contentHeight > this.containerHeight
  }

  // 是否需要水平滚动条
  needsHorizontalScrollbar(): boolean {
    return this.contentWidth > this.containerWidth
  }

  // 设置单个行高
  setRowHeight(row: number, height: number): void {
    if (height === this.defaultRowHeight) {
      this.rowHeights.delete(row)
    } else {
      this.rowHeights.set(row, height)
    }
    this.calculateContentSize()
    this.calculateMaxScroll()
  }
  
  // 批量设置行高
  setRowHeights(heights: Map<number, number>): void {
    this.rowHeights = new Map(heights)
    this.calculateContentSize()
    this.calculateMaxScroll()
  }
  
  // 获取行高
  getRowHeight(row: number): number {
    return this.rowHeights.get(row) || this.defaultRowHeight
  }
  
  // 重置所有行高
  resetRowHeights(): void {
    this.rowHeights.clear()
    this.calculateContentSize()
    this.calculateMaxScroll()
  }

  // 获取表头高度
  getHeaderHeight(): number {
    return this.headerHeight
  }

  // 获取默认行高
  getDefaultRowHeight(): number {
    return this.rowHeight
  }

  // 获取滚动条宽度
  getScrollbarWidth(): number {
    return this.scrollbarWidth
  }

  // 设置行号显示
  setRowNumberDisplay(show: boolean, width: number = 50): void {
    this.showRowNumber = show
    this.rowNumberWidth = width
    this.calculateContentSize()
    this.calculateMaxScroll()
  }

  // 私有方法

  private calculateContentSize(): void {
    // 计算内容高度（考虑动态行高）
    let totalHeight = this.headerHeight
    for (let i = 0; i < this.rowCount; i++) {
      totalHeight += this.getRowHeight(i)
    }
    this.contentHeight = totalHeight
    
    // 计算内容宽度（包括行号列）
    let totalWidth = this.columns.reduce((sum, col) => sum + (col.width || 100), 0)
    if (this.showRowNumber) {
      totalWidth += this.rowNumberWidth
    }
    this.contentWidth = totalWidth
    
    // 调试日志
    // console.log('VirtualScrollManager - 内容尺寸计算:', {
    //   contentWidth: this.contentWidth,
    //   contentHeight: this.contentHeight,
    //   containerWidth: this.containerWidth,
    //   containerHeight: this.containerHeight,
    //   needsVerticalScrollbar: this.contentHeight > this.containerHeight,
    //   needsHorizontalScrollbar: this.contentWidth > this.containerWidth,
    //   rowCount: this.rowCount,
    //   columnCount: this.columns.length,
    //   defaultRowHeight: this.defaultRowHeight,
    //   headerHeight: this.headerHeight,
    //   showRowNumber: this.showRowNumber,
    //   rowNumberWidth: this.rowNumberWidth
    // })
  }

  private calculateMaxScroll(): void {
    this.maxScrollTop = Math.max(0, this.contentHeight - this.containerHeight)
    this.maxScrollLeft = Math.max(0, this.contentWidth - this.containerWidth)
    
    // 确保当前滚动位置在有效范围内
    this.setScrollPosition(this.scrollTop, this.scrollLeft)
  }
} 